﻿//-----------------------------------------------------------------------
// <Copyright>
// * Copyright (C) 2022 RuYiAdmin All Rights Reserved
// </Copyright>
//-----------------------------------------------------------------------

using RuYiAdmin.Net.CommonInfrastructure.Configurations;
using RuYiAdmin.Net.CommonInfrastructure.Models;
using RuYiAdmin.Net.EntityDataModel.DataTransformationModel.SystemModel;
using RuYiAdmin.Net.EntityDataModel.EntityModel.SystemModel;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.FrameworkInterface;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.SystemInterface;
using RuYiAdmin.Net.ServiceLayer.BaseService.Implementation;
using RuYiAdmin.Net.ServiceLayer.BusinessService.Interface.SystemInterface;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RuYiAdmin.Net.ServiceLayer.BusinessService.Implementation.SystemImplementation
{
    /// <summary>
    /// 行政区域服务层实现
    /// </summary>
    public class SysAreaService : RuYiAdminBaseService<SysArea>, ISysAreaService
    {
        #region 属性及构造函数

        /// <summary>
        /// 行政区域仓储实例
        /// </summary>
        private readonly ISysAreaRepository AreaRepository;

        /// <summary>
        /// Redis仓储实例
        /// </summary>
        private readonly IRedisRepository RedisRepository;

        /// <summary>
        /// 业务日志仓储接口实例
        /// </summary>
        private readonly ILoggerRepository LoggerRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="AreaRepository"></param>
        /// <param name="RedisRepository"></param>
        /// <param name="LoggerRepository"></param>
        public SysAreaService(ISysAreaRepository AreaRepository,
                              IRedisRepository RedisRepository,
                              ILoggerRepository LoggerRepository) : base(AreaRepository)
        {
            this.AreaRepository = AreaRepository;
            this.RedisRepository = RedisRepository;
            this.LoggerRepository = LoggerRepository;
        }

        #endregion

        #region 获取行政区域树

        /// <summary>
        /// 获取行政区域树
        /// </summary>
        /// <returns></returns>
        public async Task<QueryResponseResult<SysAreaDTO>> GetAreaTreeNodes()
        {
            return await Task.Run(async () =>
            {
                var result = new List<SysAreaDTO>();

                var areas = await this.RedisRepository.GetAsync<List<SysAreaDTO>>(RuYiGlobalConfig.SystemCacheConfig.AreaCacheName);
                var parentAreas = areas.Where(t => t.ParentAreaCode == "0").OrderBy(t => t.AreaCode).ToList();

                foreach (var item in parentAreas)
                {
                    GetAreaChildren(item, areas);
                }

                result.AddRange(parentAreas);

                var queryResponseResult = QueryResponseResult<SysAreaDTO>.Success(result);
                return queryResponseResult;
            });
        }

        #endregion

        #region 加载行政区域缓存

        /// <summary>
        /// 加载行政区域缓存
        /// </summary>
        public async Task LoadSysAreaCache()
        {
            var areas = await this.AreaRepository.GetListAsync<SysAreaDTO>();
            await this.RedisRepository.SetAsync(RuYiGlobalConfig.SystemCacheConfig.AreaCacheName, areas, -1);

            this.LoggerRepository.Info("系统行政区域缓存加载完成");
        }

        #endregion

        #region 清理行政区域缓存

        /// <summary>
        /// 清理行政区域缓存
        /// </summary>
        public async Task ClearSysAreaCache()
        {
            await this.RedisRepository.DeleteAsync(new string[] { RuYiGlobalConfig.SystemCacheConfig.AreaCacheName });

            this.LoggerRepository.Info("系统行政区域缓存清理完成");
        }

        #endregion

        #region 服务层私有方法

        /// <summary>
        /// 递归树
        /// </summary>
        /// <param name="root">根节点</param>
        /// <param name="areas">区域列表</param>
        private void GetAreaChildren(SysAreaDTO root, List<SysAreaDTO> areas)
        {
            var list = areas.Where(t => t.ParentAreaCode == root.AreaCode).ToList();
            if (list.Count > 0)
            {
                root.Children = new List<SysAreaDTO>();
                root.Children.AddRange(list.OrderBy(t => t.AreaCode).ToList());
                foreach (var item in list)
                {
                    GetAreaChildren(item, areas);
                }
            }
        }

        #endregion
    }
}
